package com.ruoyi.report_tg.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.BigDecimalUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.syrw.annotation.DealHeh;
import com.ruoyi.syrw.annotation.FIllBasicInfo;
import com.ruoyi.report_tg.domain.vo.YexVo;
import com.ruoyi.syrw.common.LineFunction;
import com.ruoyi.syrw.common.LineUtil;
import com.ruoyi.system.service.ISysConfigService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.report_tg.domain.bo.TdjxhsljlbBsInfoBo;
import com.ruoyi.report_tg.domain.vo.TdjxhsljlbBsInfoVo;
import com.ruoyi.report_tg.domain.TdjxhsljlbBsInfo;
import com.ruoyi.report_tg.mapper.TdjxhsljlbBsInfoMapper;
import com.ruoyi.report_tg.service.ITdjxhsljlbBsInfoService;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Collection;

import static java.lang.Math.log10;

/**
 * 土的限界含水率记录Service业务层处理
 *
 * @author zyb
 * @date 2024-05-24
 */
@RequiredArgsConstructor
@Service
@Transactional
public class TdjxhsljlbBsInfoServiceImpl implements ITdjxhsljlbBsInfoService {

    private final TdjxhsljlbBsInfoMapper baseMapper;
    private final ISysConfigService sysConfigService;

    /**
     * 查询土的限界含水率记录
     */
    @Override
    @FIllBasicInfo
    public TdjxhsljlbBsInfoVo queryById(Long excelId){
        return baseMapper.selectVoById(excelId);
    }

    /**
     * 查询土的限界含水率记录列表
     */
    @Override
    public TableDataInfo<TdjxhsljlbBsInfoVo> queryPageList(TdjxhsljlbBsInfoBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<TdjxhsljlbBsInfo> lqw = buildQueryWrapper(bo);
        Page<TdjxhsljlbBsInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询土的限界含水率记录列表
     */
    @Override
    public List<TdjxhsljlbBsInfoVo> queryList(TdjxhsljlbBsInfoBo bo) {
        LambdaQueryWrapper<TdjxhsljlbBsInfo> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<TdjxhsljlbBsInfo> buildQueryWrapper(TdjxhsljlbBsInfoBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<TdjxhsljlbBsInfo> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getTotalPage() != null, TdjxhsljlbBsInfo::getTotalPage, bo.getTotalPage());
        lqw.eq(bo.getPage() != null, TdjxhsljlbBsInfo::getPage, bo.getPage());
        lqw.eq(StringUtils.isNotBlank(bo.getJilbh()), TdjxhsljlbBsInfo::getJilbh, bo.getJilbh());
//        lqw.eq(StringUtils.isNotBlank(bo.getJiancdwmc()), TdjxhsljlbBsInfo::getJiancdwmc, bo.getJiancdwmc());
//        lqw.eq(StringUtils.isNotBlank(bo.getGongcbwyt()), TdjxhsljlbBsInfo::getGongcbwyt, bo.getGongcbwyt());
//        lqw.eq(StringUtils.isNotBlank(bo.getYangpmc()), TdjxhsljlbBsInfo::getYangpmc, bo.getYangpmc());
//        lqw.eq(StringUtils.isNotBlank(bo.getYangpbh()), TdjxhsljlbBsInfo::getYangpbh, bo.getYangpbh());
//        lqw.eq(StringUtils.isNotBlank(bo.getYangpsl()), TdjxhsljlbBsInfo::getYangpsl, bo.getYangpsl());
//        lqw.eq(StringUtils.isNotBlank(bo.getYangpzt()), TdjxhsljlbBsInfo::getYangpzt, bo.getYangpzt());
//        lqw.eq(bo.getYangpsj() != null, TdjxhsljlbBsInfo::getYangpsj, bo.getYangpsj());
//        lqw.eq(StringUtils.isNotBlank(bo.getShiyjcrq()), TdjxhsljlbBsInfo::getShiyjcrq, bo.getShiyjcrq());
//        lqw.eq(StringUtils.isNotBlank(bo.getShiytjwd()), TdjxhsljlbBsInfo::getShiytjwd, bo.getShiytjwd());
//        lqw.eq(StringUtils.isNotBlank(bo.getShiytjsd()), TdjxhsljlbBsInfo::getShiytjsd, bo.getShiytjsd());
//        lqw.eq(StringUtils.isNotBlank(bo.getJiancyj()), TdjxhsljlbBsInfo::getJiancyj, bo.getJiancyj());
//        lqw.eq(StringUtils.isNotBlank(bo.getPandyj()), TdjxhsljlbBsInfo::getPandyj, bo.getPandyj());
//        lqw.eq(StringUtils.isNotBlank(bo.getZhuyyqsbmcjbh()), TdjxhsljlbBsInfo::getZhuyyqsbmcjbh, bo.getZhuyyqsbmcjbh());
//        lqw.eq(StringUtils.isNotBlank(bo.getFujsm()), TdjxhsljlbBsInfo::getFujsm, bo.getFujsm());
//        lqw.eq(bo.getH11() != null, TdjxhsljlbBsInfo::getH11, bo.getH11());
//        lqw.eq(bo.getH12() != null, TdjxhsljlbBsInfo::getH12, bo.getH12());
//        lqw.eq(bo.getH13() != null, TdjxhsljlbBsInfo::getH13, bo.getH13());
//        lqw.eq(bo.getH21() != null, TdjxhsljlbBsInfo::getH21, bo.getH21());
//        lqw.eq(bo.getH22() != null, TdjxhsljlbBsInfo::getH22, bo.getH22());
//        lqw.eq(bo.getH23() != null, TdjxhsljlbBsInfo::getH23, bo.getH23());
//        lqw.eq(bo.getPingjh1() != null, TdjxhsljlbBsInfo::getPingjh1, bo.getPingjh1());
//        lqw.eq(bo.getPingjh2() != null, TdjxhsljlbBsInfo::getPingjh2, bo.getPingjh2());
//        lqw.eq(bo.getPingjh3() != null, TdjxhsljlbBsInfo::getPingjh3, bo.getPingjh3());
//        lqw.eq(StringUtils.isNotBlank(bo.getHeh11()), TdjxhsljlbBsInfo::getHeh11, bo.getHeh11());
//        lqw.eq(bo.getHezl11() != null, TdjxhsljlbBsInfo::getHezl11, bo.getHezl11());
//        lqw.eq(bo.getHejstzl11() != null, TdjxhsljlbBsInfo::getHejstzl11, bo.getHejstzl11());
//        lqw.eq(bo.getHejgtzl11() != null, TdjxhsljlbBsInfo::getHejgtzl11, bo.getHejgtzl11());
//        lqw.eq(bo.getShuifzl11() != null, TdjxhsljlbBsInfo::getShuifzl11, bo.getShuifzl11());
//        lqw.eq(bo.getGantzl11() != null, TdjxhsljlbBsInfo::getGantzl11, bo.getGantzl11());
//        lqw.eq(bo.getHansl11() != null, TdjxhsljlbBsInfo::getHansl11, bo.getHansl11());
//        lqw.eq(StringUtils.isNotBlank(bo.getHeh12()), TdjxhsljlbBsInfo::getHeh12, bo.getHeh12());
//        lqw.eq(bo.getHezl12() != null, TdjxhsljlbBsInfo::getHezl12, bo.getHezl12());
//        lqw.eq(bo.getHejstzl12() != null, TdjxhsljlbBsInfo::getHejstzl12, bo.getHejstzl12());
//        lqw.eq(bo.getHejgtzl12() != null, TdjxhsljlbBsInfo::getHejgtzl12, bo.getHejgtzl12());
//        lqw.eq(bo.getShuifzl12() != null, TdjxhsljlbBsInfo::getShuifzl12, bo.getShuifzl12());
//        lqw.eq(bo.getGantzl12() != null, TdjxhsljlbBsInfo::getGantzl12, bo.getGantzl12());
//        lqw.eq(bo.getHansl12() != null, TdjxhsljlbBsInfo::getHansl12, bo.getHansl12());
//        lqw.eq(bo.getHanslpjz1() != null, TdjxhsljlbBsInfo::getHanslpjz1, bo.getHanslpjz1());
//        lqw.eq(StringUtils.isNotBlank(bo.getHeh21()), TdjxhsljlbBsInfo::getHeh21, bo.getHeh21());
//        lqw.eq(bo.getHezl21() != null, TdjxhsljlbBsInfo::getHezl21, bo.getHezl21());
//        lqw.eq(bo.getHejstzl21() != null, TdjxhsljlbBsInfo::getHejstzl21, bo.getHejstzl21());
//        lqw.eq(bo.getHejgtzl21() != null, TdjxhsljlbBsInfo::getHejgtzl21, bo.getHejgtzl21());
//        lqw.eq(bo.getShuifzl21() != null, TdjxhsljlbBsInfo::getShuifzl21, bo.getShuifzl21());
//        lqw.eq(bo.getGantzl21() != null, TdjxhsljlbBsInfo::getGantzl21, bo.getGantzl21());
//        lqw.eq(bo.getHansl21() != null, TdjxhsljlbBsInfo::getHansl21, bo.getHansl21());
//        lqw.eq(StringUtils.isNotBlank(bo.getHeh22()), TdjxhsljlbBsInfo::getHeh22, bo.getHeh22());
//        lqw.eq(bo.getHezl22() != null, TdjxhsljlbBsInfo::getHezl22, bo.getHezl22());
//        lqw.eq(bo.getHejstzl22() != null, TdjxhsljlbBsInfo::getHejstzl22, bo.getHejstzl22());
//        lqw.eq(bo.getHejgtzl22() != null, TdjxhsljlbBsInfo::getHejgtzl22, bo.getHejgtzl22());
//        lqw.eq(bo.getShuifzl22() != null, TdjxhsljlbBsInfo::getShuifzl22, bo.getShuifzl22());
//        lqw.eq(bo.getGantzl22() != null, TdjxhsljlbBsInfo::getGantzl22, bo.getGantzl22());
//        lqw.eq(bo.getHansl22() != null, TdjxhsljlbBsInfo::getHansl22, bo.getHansl22());
//        lqw.eq(bo.getHanslpjz2() != null, TdjxhsljlbBsInfo::getHanslpjz2, bo.getHanslpjz2());
//        lqw.eq(StringUtils.isNotBlank(bo.getHeh31()), TdjxhsljlbBsInfo::getHeh31, bo.getHeh31());
//        lqw.eq(bo.getHezl31() != null, TdjxhsljlbBsInfo::getHezl31, bo.getHezl31());
//        lqw.eq(bo.getHejstzl31() != null, TdjxhsljlbBsInfo::getHejstzl31, bo.getHejstzl31());
//        lqw.eq(bo.getHejgtzl31() != null, TdjxhsljlbBsInfo::getHejgtzl31, bo.getHejgtzl31());
//        lqw.eq(bo.getShuifzl31() != null, TdjxhsljlbBsInfo::getShuifzl31, bo.getShuifzl31());
//        lqw.eq(bo.getGantzl31() != null, TdjxhsljlbBsInfo::getGantzl31, bo.getGantzl31());
//        lqw.eq(bo.getHansl31() != null, TdjxhsljlbBsInfo::getHansl31, bo.getHansl31());
//        lqw.eq(StringUtils.isNotBlank(bo.getHeh32()), TdjxhsljlbBsInfo::getHeh32, bo.getHeh32());
//        lqw.eq(bo.getHezl32() != null, TdjxhsljlbBsInfo::getHezl32, bo.getHezl32());
//        lqw.eq(bo.getHejstzl32() != null, TdjxhsljlbBsInfo::getHejstzl32, bo.getHejstzl32());
//        lqw.eq(bo.getHejgtzl32() != null, TdjxhsljlbBsInfo::getHejgtzl32, bo.getHejgtzl32());
//        lqw.eq(bo.getShuifzl32() != null, TdjxhsljlbBsInfo::getShuifzl32, bo.getShuifzl32());
//        lqw.eq(bo.getGantzl32() != null, TdjxhsljlbBsInfo::getGantzl32, bo.getGantzl32());
//        lqw.eq(bo.getHansl32() != null, TdjxhsljlbBsInfo::getHansl32, bo.getHansl32());
//        lqw.eq(bo.getHanslpjz3() != null, TdjxhsljlbBsInfo::getHanslpjz3, bo.getHanslpjz3());
//        lqw.eq(bo.getYex() != null, TdjxhsljlbBsInfo::getYex, bo.getYex());
//        lqw.eq(bo.getSux() != null, TdjxhsljlbBsInfo::getSux, bo.getSux());
//        lqw.eq(bo.getSuxzs() != null, TdjxhsljlbBsInfo::getSuxzs, bo.getSuxzs());
        return lqw;
    }

    /**
     * 新增土的限界含水率记录
     */
    @Override
    public Boolean insertByBo(TdjxhsljlbBsInfoBo bo) {
        TdjxhsljlbBsInfo add = BeanUtil.toBean(bo, TdjxhsljlbBsInfo.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setExcelId(add.getExcelId());
        }
        return flag;
    }

    /**
     * 修改土的限界含水率记录
     */
    @Override
    @DealHeh
    public Boolean updateByBo(TdjxhsljlbBsInfoBo bo) {
        TdjxhsljlbBsInfo update = BeanUtil.toBean(bo, TdjxhsljlbBsInfo.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(TdjxhsljlbBsInfo entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除土的限界含水率记录
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public YexVo getYex(TdjxhsljlbBsInfoBo bo) {
//        LineFunction lineParam = LineUtil.getGeneralLine(data);
        YexVo yexVo = new YexVo();
//        yexVo.setYex(BigDecimalUtil.stpTrailZero(BigDecimalUtil.divide(
//            BigDecimalUtil.subtract(new BigDecimal(20), lineParam.getB(), 2),
//            lineParam.getK(), 2
//        )));
        if (BigDecimalUtil.isNotEmpty(bo.getHanslpjz3()) && BigDecimalUtil.isNotEmpty(bo.getPingjh3()) && BigDecimalUtil.isNotEmpty(bo.getPingjh2())
            && BigDecimalUtil.isNotEmpty(bo.getHanslpjz2()) && BigDecimalUtil.isNotEmpty(bo.getHanslpjz1()) && BigDecimalUtil.isNotEmpty(bo.getPingjh1())) {
            double G22 = bo.getHanslpjz3().doubleValue();
            double G14 = bo.getPingjh3().doubleValue();
            double E22 = bo.getHanslpjz2().doubleValue();
            double C22 = bo.getHanslpjz1().doubleValue();
            double E14 = bo.getPingjh2().doubleValue();
            double C14 = bo.getPingjh1().doubleValue();
            // 增加对两条线斜率的校验
            checkPoint(G22, G14, E22, E14, C22, C14);
            double T13 = G22 / (0.524 * G22 - 7.606);
            Assert.state(T13 > 0 && G22 > 0 && G14 > 0 && E22 > 0 && E14 > 0 && C22 > 0 && C14 > 0, "计算异常");

            double T14 = Math.pow(10, (log10(G22) + ((log10(G22) - log10(E22)) * (log10(T13) - log10(G14))) / (log10(G14) - log10(E14))));
            double T15 = Math.pow(10, (log10(G22) + ((log10(G22) - log10(C22)) * (log10(T13) - log10(G14))) / (log10(G14) - log10(C14))));
            double T17 = (T14 + T15) / 2;

            double WL = Math.pow(10, (log10(G22) + ((log10(G22) - log10(T17)) * (log10(20) - log10(G14))) / (log10(G14) - log10(T13))));
            if (Double.isNaN(WL)) {
                throw new ServiceException("计算异常");
            }
            yexVo.setYex(BigDecimalUtil.defaultValue(WL, 1));
            double T19 = WL/(0.524*WL - 7.606);
            double WP = Math.pow(10, (log10(G22) + ((log10(G22) - log10(T17)) * (log10(T19) - log10(G14))) / (log10(G14) - log10(T19))));
            if (Double.isNaN(WP)) {
                throw new ServiceException("计算异常");
            }
            yexVo.setSux(BigDecimalUtil.defaultValue(WP, 1));
            double Ip = WL - WP;
            yexVo.setSuxzs(BigDecimalUtil.defaultValue(Ip, 1));
        }

        return yexVo;
    }

    /**
     * 检查三个点是否在同一条直线上，通过比较线AB和线AC的斜率来判断
     * 此方法用于确保三点近似共线，考虑到实际应用中可能存在微小偏差，引入阈值概念
     *
     * @param x1 第一个点的x坐标
     * @param y1 第一个点的y坐标
     * @param x2 第二个点的x坐标
     * @param y2 第二个点的y坐标
     * @param x3 第三个点的x坐标
     * @param y3 第三个点的y坐标
     * @throws ServiceException 如果系统缺少配置或配置错误，或者线AB与线AC的斜率超过设定阈值
     */
    private void checkPoint(double x1, double y1, double x2, double y2, double x3, double y3) {
        // 根据两个点计算线AB和线AC的方程
        LineFunction lineAB = LineUtil.getGeneralLine(new double[][]{{x1, y1}, {x2, y2}});
        LineFunction lineAC = LineUtil.getGeneralLine(new double[][]{{x1, y1}, {x3, y3}});

        // 从系统配置中获取斜率偏差阈值
        String threshold = sysConfigService.selectConfigByKey("yex.k.threshold");
        double t;

        // 检查阈值配置是否为空，如果为空或格式错误，抛出异常
        try {
            if (StrUtil.isEmpty(threshold)) {
                throw new ServiceException("系统缺少系统参数土的界限含水率线AB与线AC的斜率偏差阈值参数，请联系管理员添加");
            }
            t = Double.parseDouble(threshold);
        } catch (NumberFormatException e) {
            throw new ServiceException("系统参数土的界限含水率线AB与线AC的斜率偏差阈值配置错误");
        }

        // 比较线AB和线AC的斜率，如果偏差超过阈值，抛出异常
        if (((Math.abs(lineAB.getK() - lineAC.getK())) / Math.abs(lineAC.getK())) >= t) {
            throw new ServiceException("线AB与线AC的斜率超过设定阈值，数据不合格。");
        }
    }

}
